﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DatabaseManagerLib;
using System.Runtime.Remoting.Messaging;
using System.Threading;

namespace ServerLib
{
    public sealed class RemoteServer : MarshalByRefObject, IRemoteServer
    {
        private DatabaseManager _managerDb; // object for used server's database
        private ArrayList _clients; // Online clients
        private String _chatSession; // history of chating

        #region Constructor
        public RemoteServer()
        {
            _managerDb = new DatabaseManager(Properties.Resources.ConnectionDbSource, Properties.Resources.ConnectionDbNameDatabase);
            _chatSession = "";
            _clients = new ArrayList();
            Console.WriteLine(_managerDb.Connect());
        }

        #endregion

        /// <summary>
        /// Method returt list of online clients
        /// </summary>
        /// <returns>_clients</returns>
        public ArrayList GetListOfClients()
        {
            return _clients;
        }

        /// <summary>
        /// Method return client info
        /// </summary>
        /// <param name="login">String login</param>
        /// <returns>ClientInfo</returns>
        public ClientInfo GetClientInfo(String login)
        {
            return new ClientInfo(login,
                _managerDb.GetName(login),
                _managerDb.GetLastName(login),
                _managerDb.GetBirthDay(login),
                _managerDb.GetSex(login) == "Male" ? ClientInfo.EnumSex.Male : ClientInfo.EnumSex.Female
                );
        }

        /// <summary>
        /// Method NotifyClients about send Message
        /// </summary>
        /// <param name="args">EventArgs Chat client</param>
        private void NotifyClients(ChatEventArgs args)
        {
            lock (this)
            {
                System.Delegate[] invkList = ChatEvent.GetInvocationList();

                IEnumerator ie = invkList.GetEnumerator();
                while (ie.MoveNext())
                {
                    ChatEventHandler handler = (ChatEventHandler)ie.Current;
                    try
                    {
                        IAsyncResult ar = handler.BeginInvoke(this, args, null, null);
                    }
                    catch (Exception)
                    {
                        ChatEvent -= handler;
                    }
                }
            }
        }

        /// <summary>
        /// Method return history of chating
        /// </summary>
        /// <returns>_chatSession</returns>
        public String GetChatSession()
        {
            return _chatSession;
        }

        /// <summary>
        /// Method add new message
        /// </summary>
        /// <param name="login">login</param>
        /// <param name="message">message</param>
        public void AddMessage(String login, String message)
        {
            if (login != null && message != null)
            {
                lock(_chatSession)
                {
                    _chatSession += login + " : " + message + Environment.NewLine;
                    Console.WriteLine(login + ": wrote message...");
                    NotifyClients(new ChatEventArgs(login, message));
                }
            }
        }

        /// <summary>
        /// Add client to online list
        /// </summary>
        /// <param name="login">login</param>
        public void AddClient(String login)
        {
            if (login != null)
            {
                lock (_clients)
                {
                    _clients.Add(login);
                }
            }
        }

        /// <summary>
        /// Remove Client from online list
        /// </summary>
        /// <param name="login"></param>
        public void RemoveClient(String login)
        {
            if (login != null)
            {
                lock (_clients)
                {
                    _clients.Remove(login);
                }
            }
        }

        /// <summary>
        /// Method Check password
        /// </summary>
        /// <param name="login">login</param>
        /// <param name="password">password</param>
        /// <returns>result(true, false)</returns>
        public bool CheckPassword(String login, String password)
        {
            String truePassword = _managerDb.GetPassword(login);
            if (password == truePassword)
            {
                return true;
            }
            else 
            {
                return false;
            }
        }

        /// <summary>
        /// Method Check or there is login in database  
        /// </summary>
        /// <param name="login">login</param>
        /// <returns>result(true, false)</returns>
        public bool CheckLogin(String login)
        {
            List<String> list = _managerDb.GetListLogin();
            foreach (String clientLogin in list)
            {
                if (clientLogin == login)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Method Create new user in database
        /// </summary>
        /// <param name="login"></param>
        /// <param name="password"></param>
        public void CreateUser(String login, String password)
        {
            _managerDb.CreateUser(login, password);
        }

        /// <summary>
        /// Method remouve user from database
        /// </summary>
        /// <param name="login">login</param>
        /// <param name="password">password</param>
        public void RemoteUser(String login, String password)
        {
            if (CheckPassword(login, password))
            _managerDb.DeleteUser(login);
        }

        /// <summary>
        /// Method get info about user
        /// </summary>
        /// <param name="login">login</param>
        /// <param name="password">password</param>
        /// <param name="name">name of user</param>
        /// <param name="lastName">last name of user</param>
        /// <param name="birthday">birthday of user</param>
        /// <param name="sex">sex of user</param>
        public void SetUserInfo(String login, String password, String name, String lastName, String birthday, ClientInfo.EnumSex sex)
        {
            if (CheckPassword(login, password))
            {
                if (name.TrimEnd() != "")
                {
                    _managerDb.SetName(login, name);
                }
                if (lastName.TrimEnd() != "")
                {
                    _managerDb.SetLastName(login, lastName);
                }
                if (birthday.TrimEnd() != "")
                {
                    _managerDb.SetBirthDay(login, birthday);
                }
                _managerDb.SetSex(login, sex.ToString());
            }
        }

        public void SetUserInfo(String login, String name, String lastName, String birthday, ClientInfo.EnumSex sex)
        {
            if (name.TrimEnd() != "")
            {
                _managerDb.SetName(login, name);
            }
            if (lastName.TrimEnd() != "")
            {
                _managerDb.SetLastName(login, lastName);
            }
            if (birthday.TrimEnd() != "")
            {
                _managerDb.SetBirthDay(login, birthday);
            }
            _managerDb.SetSex(login, sex.ToString());

        }

        /// <summary>
        /// Method change password of user in database
        /// </summary>
        /// <param name="login">login</param>
        /// <param name="password">password</param>
        public void ChangePassword(String login, String password)
        {
            _managerDb.SetPassword(login, password);
        }

        public event ChatEventHandler ChatEvent;
    }
}
